/*
 * PhotonRTOS础光实时操作系统 -- 抢占
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Baoyou Xie <xiebaoyou@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#ifndef _OS_PREEMPT_H
#define _OS_PREEMPT_H

#include <photon/process.h>
#include <photon/double_list.h>

#define PREEMPT_BITS	8
#define SOFTIRQ_BITS	8
#define HARDIRQ_BITS	12

#define PREEMPT_SHIFT	0
#define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
#define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)

#define __IRQ_MASK(x)	((1UL << (x))-1)

#define HARDIRQ_MASK	(__IRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
#define SOFTIRQ_MASK	(__IRQ_MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)

#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)

#define PREEMPT_ACTIVE	0x40000000U

#define add_preempt_count(val)	do { preempt_count() += (val);	; } while (false)
#define sub_preempt_count(val)	do { preempt_count() -= (val);	; } while (false)

#define inc_preempt_count() add_preempt_count(1U)
#define dec_preempt_count() sub_preempt_count(1U)

#define preempt_count()	(current_proc_info()->preempt_count)

asmlinkage void preempt_schedule(void);
asmlinkage void preempt_in_irq(void);

#define preempt_disable() \
do { \
	inc_preempt_count(); \
	barrier(); \
} while (false)

#define preempt_enable_no_resched() \
do { \
	barrier(); \
	dec_preempt_count(); \
} while (false)

#define preempt_check_resched() \
do { \
	if ((test_process_flag(PROCFLAG_NEED_RESCHED) != 0)) { \
		preempt_schedule(); \
	}\
} while (false)

#define preempt_enable() \
do { \
	preempt_enable_no_resched(); \
	barrier(); \
	preempt_check_resched(); \
} while (false)


#endif /* _OS_PREEMPT_H */
